// TestRunnerWnd.h : Declaration of the CTestRunnerWnd

#pragma once
#include "resource.h"       // main symbols

#include "AddIn.h"
#include "TestTree.h"
#include "TestRunMonitorThread.h"
#include "ITestRunNotification.h"

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

// CTestRunnerWnd

class ATL_NO_VTABLE CTestRunnerWnd :
	public CComObjectRootEx<CComSingleThreadModel>,
	public IDispatchImpl<ITestRunnerWnd, &IID_ITestRunnerWnd, &LIBID_CputLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
	public CComCoClass<CTestRunnerWnd, &CLSID_TestRunnerWnd>,
	public IPersistStreamInitImpl<CTestRunnerWnd>,
	public IOleControlImpl<CTestRunnerWnd>,
	public IOleObjectImpl<CTestRunnerWnd>,
	public IOleInPlaceActiveObjectImpl<CTestRunnerWnd>,
	public IViewObjectExImpl<CTestRunnerWnd>,
	public IOleInPlaceObjectWindowlessImpl<CTestRunnerWnd>,
	public ISupportErrorInfo,
	public IPersistStorageImpl<CTestRunnerWnd>,
	public ISpecifyPropertyPagesImpl<CTestRunnerWnd>,
	public IQuickActivateImpl<CTestRunnerWnd>,
#ifndef _WIN32_WCE
	public IDataObjectImpl<CTestRunnerWnd>,
#endif
	public IProvideClassInfo2Impl<&CLSID_TestRunnerWnd, NULL, &LIBID_CputLib>,
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
	public IObjectSafetyImpl<CTestRunnerWnd, INTERFACESAFE_FOR_UNTRUSTED_CALLER>,
#endif
	public CComCompositeControl<CTestRunnerWnd>,
	public ITestRunNotification
{
public:
	CTestRunnerWnd() : m_pIExchangeControl(NULL)
	{
		m_bWindowOnly = TRUE;
		CalcExtent(m_sizeExtent);
	}

DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_INSIDEOUT |
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST
)

DECLARE_REGISTRY_RESOURCEID(IDR_TESTRUNNERWND)


BEGIN_COM_MAP(CTestRunnerWnd)
	COM_INTERFACE_ENTRY(ITestRunnerWnd)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IViewObjectEx)
	COM_INTERFACE_ENTRY(IViewObject2)
	COM_INTERFACE_ENTRY(IViewObject)
	COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceObject)
	COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
	COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
	COM_INTERFACE_ENTRY(IOleControl)
	COM_INTERFACE_ENTRY(IOleObject)
	COM_INTERFACE_ENTRY(IPersistStreamInit)
	COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
	COM_INTERFACE_ENTRY(ISupportErrorInfo)
	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
	COM_INTERFACE_ENTRY(IQuickActivate)
	COM_INTERFACE_ENTRY(IPersistStorage)
#ifndef _WIN32_WCE
	COM_INTERFACE_ENTRY(IDataObject)
#endif
	COM_INTERFACE_ENTRY(IProvideClassInfo)
	COM_INTERFACE_ENTRY(IProvideClassInfo2)
#ifdef _WIN32_WCE // IObjectSafety is required on Windows CE for the control to be loaded correctly
	COM_INTERFACE_ENTRY_IID(IID_IObjectSafety, IObjectSafety)
#endif
END_COM_MAP()

BEGIN_PROP_MAP(CTestRunnerWnd)
	PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
	PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
	// Example entries
	// PROP_ENTRY("Property Description", dispid, clsid)
	// PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_MSG_MAP(CTestRunnerWnd)
	MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
	MESSAGE_HANDLER(WM_SIZE, OnSize)
	COMMAND_HANDLER(IDC_CB_TESTPROJECTS, CBN_SELCHANGE, OnCbnSelchangeCbTestprojects)
	COMMAND_HANDLER(IDC_BT_REFRESH, BN_CLICKED, OnBnClickedBtRefresh)
	COMMAND_HANDLER(IDC_BT_RUNALL, BN_CLICKED, OnBnClickedBtRunall)
	COMMAND_HANDLER(IDC_BT_RUNCHECKED, BN_CLICKED, OnBnClickedBtRunchecked)
	COMMAND_HANDLER(IDC_BT_DEBUGALL, BN_CLICKED, OnBnClickedBtDebugall)
	COMMAND_HANDLER(IDC_BT_DEBUGCHECKED, BN_CLICKED, OnBnClickedBtDebugchecked)
	NOTIFY_HANDLER(IDC_TESTRUNLIST, NM_CUSTOMDRAW, OnNMCustomdrawTestRunList)
	NOTIFY_HANDLER(IDC_TESTRUNLIST, NM_CLICK, OnNMClickTestRunList)
	NOTIFY_HANDLER(IDC_TESTRUNLIST, NM_DBLCLK, OnDblClickTestRunList)
	NOTIFY_HANDLER(IDC_TESTRUNLIST, LVN_KEYDOWN, OnLvnKeydownTestRunList)
	NOTIFY_HANDLER(IDC_TESTRUNLIST, NM_RCLICK, OnNMRClickTestRunList)
	MESSAGE_HANDLER(WM_TESTAPPNOTIFY, OnClientNotify)
	MESSAGE_HANDLER(WM_MONITORTHREADNOTIFY, OnMonitorThreadNotify)
	MESSAGE_HANDLER(WM_TIMER, OnTimer)
	CHAIN_MSG_MAP(CComCompositeControl<CTestRunnerWnd>)
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

BEGIN_SINK_MAP(CTestRunnerWnd)
	//Make sure the Event Handlers have __stdcall calling convention
END_SINK_MAP()

	STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
	{
		if (dispid == DISPID_AMBIENT_BACKCOLOR)
		{
			SetBackgroundColorFromAmbient();
			FireViewChange();
		}
		return IOleControlImpl<CTestRunnerWnd>::OnAmbientPropertyChange(dispid);
	}
	// ISupportsErrorInfo
	STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
	{
		static const IID* arr[] =
		{
			&IID_ITestRunnerWnd,
		};

		for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
		{
			if (InlineIsEqualGUID(*arr[i], riid))
				return S_OK;
		}
		return S_FALSE;
	}

	// IViewObjectEx
	DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

	enum { IDD = IDD_TESTRUNNERWND };

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		m_bAll = FALSE;
		m_imgStatusList = ImageList_Create(14, 14, ILC_COLOR24 | ILC_MASK, 13, 0);
		HBITMAP hBmp = LoadBitmap(_AtlModule.GetResourceInstance(), MAKEINTRESOURCE(IDB_STATUSLIST));
		ImageList_AddMasked(m_imgStatusList, hBmp, RGB(255, 0, 255));
		DeleteObject(hBmp);

		return S_OK;
	}

	void FinalRelease()
	{
		ImageList_Destroy(m_imgStatusList);
	}

public:
	void Prepare(EnvDTE80::DTE2 *pDTE, IExchangeControl *pIExchangeControl);

	LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled);
	LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	LRESULT OnCbnSelchangeCbTestprojects(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnBnClickedBtRefresh(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnBnClickedBtRunall(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnBnClickedBtRunchecked(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnBnClickedBtDebugall(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnBnClickedBtDebugchecked(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
	LRESULT OnNMCustomdrawTestRunList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& bHandled);
	LRESULT OnNMClickTestRunList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& bHandled);
	LRESULT OnLvnKeydownTestRunList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& bHandled);
	LRESULT OnNMRClickTestRunList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& bHandled);
	LRESULT OnDblClickTestRunList(int /*idCtrl*/, LPNMHDR pNMHDR, BOOL& bHandled);
	LRESULT OnClientNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
	LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

ut_private:
	enum NamedImageIndex
	{
		//status
		iPending		= 0,
		iRun			= 1,
		iStop			= 2,
		iWarning		= 3,
		iInconclusive	= 4,
		iSucceeded		= 5,
		iFailed			= 6,
		//options
		iBoxExpanded	= 7,
		iBoxCollapsed	= 8,
		iBoxChecked		= 9,
		iBoxUnchecked	= 10,
		iBoxDisabledChecked		= 11,
		iBoxDisabledUnchecked	= 12
	};

	enum ColumnId
	{
		ciImage = 0,
		ciName,
		ciReport,
		ciStatus,
		ciTime
	};

	CWindow	m_csTestProjects;
	CWindow m_csTestRunList;
	CWindow m_btRefresh,
			m_btDebugAll,
			m_btDebugChecked,
			m_btRunAll,
			m_btRunChecked;

	HIMAGELIST m_imgStatusList;

	CComPtr<EnvDTE80::DTE2> m_spDTE;
	IExchangeControl *m_pIExchangeControl;

	CAtlArray<TestGroupRun> m_aGroups;
	BOOL m_bAll;

	const CAtlArray<TestGroupRun> & GetTestGroups() const { return m_aGroups; }
	CAtlArray<TestGroupRun> & GetTestGroups() { return m_aGroups; }

	//used to store unique names of test project to identify after selection new one in the renewed solution
	CAtlArray<CAtlStringW> m_aTestProjects;
	//used to fill test projects combo box
	void FillTestProjects();
	//retrieve currently selected test project and returns TRUE if any or FALSE otherwise
	BOOL GetCurSelTestProject(OUT EnvDTE::ProjectPtr & spCurSelProject);
	//used to fill the test run list with current selected project
	void FillTestRunTree();
	//synchronize content of th test run list
	//returns the selected group index
	int Synchronize(WORD nSelGroup = 0xFFFF);

	LRESULT OnSubItemDraw(LPNMCUSTOMDRAW pNMCD);

	//set check box to bCheck value for all test groups
	void CheckUncheckAll(BOOL bCheck);

	//reset parameters in the client's test set
	static void ResetParameters(TestPackTransData & r);

	static void SychronizeWithClientTestSet(TestPackTransData & r, CAtlArray<TestGroupRun> & rTestGroupRun, BOOL bAll);
	
	void StartNotification(DWORD dwTestAppProcessId);
    void TestSet(TestPackTransData & rTestSet);
    void GroupStartNotification(DWORD nGroupParam);
    void TestStartNotification(DWORD nGroupParam, DWORD nTestParam);
    void TestEndNotification(DWORD nGroupParam, DWORD nTestParam, ERunStatus eRunStatus, __time64_t tDuration, LPCWSTR lpReport);
    void GroupEndNotification(DWORD nGroupParam, ERunStatus eRunStatus, __time64_t tDuration, LPCWSTR lpReport);
    void EndNotification();

	void AbortNotification();

	void Start(BOOL bDebug, BOOL bAll);

	CTestRunMonitorThread m_csTestRunMonitorThread;
	
	LRESULT OnMonitorThreadNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	//toggles an item's check box that is currently selected in the test run list
	void ToggleCheckInTestRunList(WORD nGroup, WORD nItem);
	
	//formats the current selected item in the test run list
	void CopyIntoClipboard(WORD nGroup, WORD nItem);
	//copis the given messages into the Winodws clipboard in the Text, Unicode Text and HTML format
	void CopyIntoClipboardMessage(const CAtlStringW & wstrMessage, const CAtlStringW & wstrHtmlMessage);
	//prepares the plain html format for the clipboard
	static void PrepareHTMLClipboardText(const CAtlStringW & wstrMessage, CAtlStringA & csRetVal);

	void NavigateToFunction(LPCWSTR lpClassName, LPCWSTR lpFunctionName);

	void ExpandGroup(WORD nGroup);
	void CollapseGroup(WORD nGroup);
};

OBJECT_ENTRY_AUTO(__uuidof(TestRunnerWnd), CTestRunnerWnd)